<?php

namespace IDock\Insurance\ZYIC\Request;

use Exception;
use IDock\IDock\IDockEnums;
use IDock\Insurance\ZYIC\Response\PremiumInquiryResponse;
use IDock\Insurance\ZYIC\ZYICEnums;
use IDock\Visitor\NonCar\NonCarProductVisitor;
use IDock\Visitor\Premium\PremiumChargingPileVisitor;
use IDock\Visitor\Premium\PremiumCoverageVisitor;
use IDock\Visitor\Premium\PremiumDeviceVisitor;
use IDock\Visitor\Premium\PremiumInquiryVisitor;
use IDock\Visitor\Premium\PremiumRelationVisitor;

class PremiumInquiryRequest extends AllZYICRequest
{
    public $route = 'channelInterface/V04';

    protected $response = PremiumInquiryResponse::class;

    protected $urlTip = '报价接口';

    /*** @var  PremiumInquiryVisitor $visitor */
    protected $visitor;

    public $systemFlag = '';

    public $planName = '';

    /**
     * @throws Exception
     */
    public function generate(): array
    {
        $this->planName = $this->visitor->getExtInfoVisitor()->argc['planName'] ?? '';
        $data = [
            'isRalationBI' => $this->visitor->biStartData ? '1' : '0',
            'isRalationCI' => $this->visitor->ciStartData ? '1' : '0',
            'prpTmain' => [
                'planName' => $this->planName,
                'systemFlag' => $this->systemFlag,
            ],
            'prpTinsureds' => $this->getRelationData(),
            'prpTitemCar' => $this->carData(),
            'prpTinvoiceInfo' => [
                'invoiceType' => '5', //暂不开票
            ],
        ];
        if ($this->visitor->biStartData) {
            $data['bi'] = $this->getBiData();
        }
        if ($this->visitor->ciStartData) {
            $data['ci'] = $this->getCiData();
        }
        //充电桩
        if ($this->visitor->getChargingPileVisitorList()) {
            $data['prpTnewEnergys'] = $this->getChargingList();
        }
        //非车
        if ($this->visitor->getNonCarInquiryVisitor()->getNonCarList()) {
            $data['nonCar'] = $this->getNonCarList();
            $data['insuranceNonCar'] = '1';//非车必填字段
        }
        return $data;
    }

    public function getNonCarList(): array
    {
        /**
         * @var NonCarProductVisitor $single
         */
        $single = $this->visitor->getNonCarInquiryVisitor()->getNonCarList()[0] ?? [];

        $nonCarType = 2;

        if (in_array($single->planCode, ['26', '28', '27', '29'])) {
            $nonCarType = 3;
        }

        return [
            'nonCarType' => $nonCarType,//2 代表乐驾保，3代表驾意险
            'insurancePlan' => $single->planCode,//非车产品计划号
            'plan' => $this->visitor->getVehicleVisitor()->vehicleSeat,
            'gasAddress' => $this->visitor->getInsuredVisitor()->address,
        ];
    }

    private function getChargingList(): array
    {
        $list = [];
        $no = 1;
        foreach ($this->visitor->getChargingPileVisitorList() as $visitor) {
            /*** @var  $visitor PremiumChargingPileVisitor */
            $list[] = [
                'serialNo' => (string)$no,
                'chargingPostType' => $visitor->chargingPileType,
                'chargingPostCode' => $visitor->chargingPileCode,
                'chargingPostYearLimit' => ZYICEnums::$chargingPileYearLimit[$visitor->chargingPileYearLimit],
                'chargingPostKind' => ZYICEnums::$chargingPileKind[$visitor->chargingPileKind],
                'chargingPostAddressType' => ZYICEnums::$chargingPileAddressType[$visitor->chargingPileAddressType],
                'chargingPostAddress' => $visitor->chargingPileAddress,
                'lossSumLimit' => $visitor->lossAmount,
                'liabilitySumLimit' => $visitor->liabilityAmount,
            ];
            $no += 1;
        }
        return $list;
    }

    /**
     * @throws Exception
     */
    private function getRelationData(): array
    {
        $insuredSource = $this->visitor->extInfoVisitor->argc['insuredSource'] ?? '5';

        if(!$insuredSource) {
            $insuredSource = '5';
        }

        $owner = $this->visitor->getOwnerVisitor();
        $ownerData = $this->customerModel($owner);
        $ownerData['insuredFlag'] = '5';
        $apply = $this->visitor->getApplicantVisitor();
        $applyData = $this->customerModel($apply);
        $applyData['insuredFlag'] = '2';
        $applyData['insuredSource'] = $insuredSource;
        $insured = $this->visitor->getInsuredVisitor();
        $insuredData = $this->customerModel($insured);
        $insuredData['insuredFlag'] = '1';

        return [
            $ownerData,
            $applyData,
            $insuredData,
        ];
    }

    /**
     * @throws Exception
     */
    private function customerModel(PremiumRelationVisitor $model): array
    {
        $arr = [
            'insuredType' => $model->typeCode == 'R1' ? '1' : '2',
            'insuredName' => $model->name,
            'identifyType' => ZYICEnums::$certificateTypeCode[$model->certificateTypeCode] ?? '',
            'identifyNumber' => $model->certificateNo,
            'postAddress' => $model->address,
            'identityValidStartDate' => $model->certificateStartDate,
            'identityValidEndDate' => $model->certificateEndDate,
            'nationality' => 'CHN',
            //'customerSource' => '05',
            'customerSource' => $this->visitor->getExtInfoVisitor()->argc['customerSource'] ?? '05',//客户来源 默认 市场国内
            'mobile' => $model->mobile
        ];
        if ($arr['insuredType'] == '1') {
            //个人
            $arr['occupationCode'] = '800';
            $arr['occupationGrade'] = '008';//职业大类
            $arr['birthday'] = $this->getBirthday($model->certificateNo);
            $arr['sex'] = $this->getGenderByIDCard($model->certificateNo);
//            $arr['age'] = '18';

            $arr['email'] = $model->email;
            $arr['insuredSource'] = '';
        } else {
            $arr['businessSourceName'] = 'O82';
        }
        return $arr;
    }

    /**
     * @throws Exception
     */
    private function getBirthday($idCard): string
    {
        if (strlen($idCard) != 18) {
            throw new Exception("身份证位数不合法");
        }
        return substr($idCard, 6, 4) . '-' . substr($idCard, 10, 2) . '-' . substr($idCard, 12, 2);
    }

    /**
     * 主信息
     * @return array
     */
    private function getBiData(): array
    {
        $data = [
            'riskCode' => $this->visitor->getVehicleVisitor()->isNewEnergy ? 'DEG' : 'DEB',
            'immeValidFlag' => intval($this->visitor->biEffectFlag),
            'startDate' => $this->visitor->biStartData ? date('Y-m-d', strtotime($this->visitor->biStartData)) : '',
            'startHour' => $this->visitor->biStartData ? '00' : '',
            'endDate' => $this->visitor->biEndData ? date('Y-m-d', strtotime($this->visitor->biEndData)) : '',
            'endHour' => $this->visitor->biStartData ? '24' : '',
//            'checkCode' => $this->visitor->getExtInfoVisitor()->argc['checkCode'] ?? '',
//            'checkCodeAnswer' => $this->visitor->getExtInfoVisitor()->argc['checkCodeAnswer'] ?? '',
            'prpTitemKinds' => $this->getCoverageList(),
            'prpTcarDevices' => $this->getDeviceList(),
            'planName' => $this->planName,
            'proposalNo' => $this->visitor->getExtInfoVisitor()->argc['proposalNoBI'] ?? ''
        ];
        if ($this->visitor->biStartData) {
            $data['startHour'] = date('H', strtotime($this->visitor->biStartData));
        }
        return $data;
    }

    private function getCiData(): array
    {
        $data = [
            'riskCode' => 'DDA',
            'immeValidFlag' => intval($this->visitor->ciEffectFlag),
            'startDate' => $this->visitor->ciStartData ? date('Y-m-d', strtotime($this->visitor->ciStartData)) : '',
            'startHour' => $this->visitor->ciEndData ? '00' : '',
            'endDate' => $this->visitor->ciEndData ? date('Y-m-d', strtotime($this->visitor->ciEndData)) : '',
            'endHour' => $this->visitor->ciEndData ? '24' : '',
            'planName' => $this->planName,
            'proposalNo' => $this->visitor->getExtInfoVisitor()->argc['proposalNoCI'] ?? ''
        ];
        if ($this->visitor->ciStartData) {
            $data['startHour'] = date('H', strtotime($this->visitor->ciStartData));
        }
        if ($this->visitor->ciEffectFlag) {
            $data['startMinute'] = date('i', strtotime($this->visitor->ciStartData));
            $data['endMinute'] = date('i', strtotime($this->visitor->ciEndData));
        }
        return $data;
    }

    /**
     * 车辆信息
     * @return array
     * @throws Exception
     */
    private function carData(): array
    {
        $data = [
            'otherNature7' => $this->visitor->getVehicleVisitor()->isNewVehicle ? '0' : '1',//是否已上牌，1 是；0 否
            'otherNature8' => intval($this->visitor->getVehicleVisitor()->nonlocalCar),//是否外地车
            'licenseNo' => $this->visitor->getVehicleVisitor()->licenseNo,
            'engineNo' => $this->visitor->getVehicleVisitor()->engineNo,
            'vinNo' => $this->visitor->getVehicleVisitor()->vin,
            'carKindCode' => ZYICEnums::$carKindCode[$this->visitor->getVehicleVisitor()->carKindCode] ?? '',//车辆种类
            'carkindClass' => $this->getCarClass(),
            'useNatureCode' => ZYICEnums::$causeType[$this->visitor->getVehicleVisitor()->causeType] ?? '',
            'enrollDate' => $this->visitor->getVehicleVisitor()->firstRegisterDate,
            'vehicleStyle' => $this->visitor->getVehicleVisitor()->vehicleStyleCode,
            'licenseKindCode' => $this->visitor->getVehicleVisitor()->licenseTypeCode,
            'newVehicleFlag' => intval($this->visitor->getVehicleVisitor()->isNewVehicle),
            'chgOwnerFlag' => intval($this->visitor->getVehicleVisitor()->isTransfer or $this->visitor->getVehicleVisitor()->isCiTransfer),
            'loanVehicleFlag' => 0,
            'vehicleCode' => $this->visitor->getVehicleVisitor()->vehicleModelCode,

            'modelEnergyType' => ZYICEnums::$energyType[$this->visitor->getVehicleVisitor()->energyTypeCode] ?? '',
            'fuelType' => ZYICEnums::$fuelType[$this->visitor->getVehicleVisitor()->energyTypeCode] ?? '',

            'carCheckStatus' => ZYICEnums::$carCheckCode[$this->visitor->getExtInfoVisitor()->carCheckCode] ?? '',//验车情况
            'certificateDate' => $this->visitor->getVehicleVisitor()->issueDate,
            'seatCount' => $this->visitor->getVehicleVisitor()->vehicleSeat,
            'tonCount' => round($this->visitor->getVehicleVisitor()->vehicleTonnage, 2) / 1000,
            'wholeWeight' => $this->visitor->getVehicleVisitor()->wholeWeight,
            'actualValue' => $this->visitor->getVehicleVisitor()->actualValue,
            'fairValue' => $this->visitor->getVehicleVisitor()->actualValue,
            'carValueType' => '1',//1实际价值；2公允价值
            'carInsuredRelation' => '0',//0 所有人
            'vehicleOwnerNature' => $this->visitor->getOwnerVisitor()->typeCode == 'R1' ? '1' : '3',
            'colorCode' => ZYICEnums::$vehicleColor[$this->visitor->vehicleVisitor->vehicleColor] ?? '',
        ];

        //协商价格
        if ($this->visitor->vehicleVisitor->negotiatedValue) {
            $data['fairValue'] = $this->visitor->vehicleVisitor->negotiatedValue;
            $data['carValueType'] = '2';
        }

        if (empty($data['carKindCode'])) {
            throw new Exception("不支持该车辆种类");
        }
        if (empty($data['useNatureCode'])) {
            throw new Exception("不支持该车辆使用性质");
        }
        if (empty($data['carCheckStatus'])) {
            throw new Exception("不支持该验车情况");
        }
        if ($this->visitor->getVehicleVisitor()->isTransfer or $this->visitor->getVehicleVisitor()->isCiTransfer) {
            $data['transferDate'] = $this->visitor->getVehicleVisitor()->transferDate;
        }
        if ($data['carCheckStatus'] == '1') {
            $data['carChecker'] = $this->visitor->getExtInfoVisitor()->carChecker;
            $data['carCheckTime'] = date('Y-m-d H:m', strtotime($this->visitor->getExtInfoVisitor()->carCheckDate));
        }
        return $data;
    }

    private function getCarClass(): string
    {
        $carType = $this->visitor->getVehicleVisitor()->carKindCode;
        $seat = $this->visitor->getVehicleVisitor()->vehicleSeat;
        $tong = round($this->visitor->getVehicleVisitor()->vehicleTonnage, 2) / 1000;
        if ($carType == '100') {
            //客车
            if ($seat < 6) {
                $code = '345002001';
            } elseif ($seat < '10') {
                $code = '345002002';
            } else {
                $code = '345002003';
            }
        } else {
            //货车
            if ($tong < '2') {
                $code = '345002008';
            } elseif ($tong < '5') {
                $code = '345002009';
            } elseif ($tong < '10') {
                $code = '345002010';
            } else {
                $code = '345002011';
            }
        }
        return $code;
    }

    /**
     * 险种信息
     * @return array
     */
    private function getCoverageList(): array
    {
        $list = [];
        $no = 1;

        $coverageList = $this->visitor->getCoverageVisitorList();
        $coverageList = array_combine(array_column($coverageList, 'coverageCode'), $coverageList);

        foreach ($coverageList as $coverage) {

            /*** @var PremiumCoverageVisitor $coverage */

            //交强险去除
            if ($coverage->coverageCode == 'C01001') {
                continue;
            }
            $one = [
                'itemKindNo' => (string)$no,
                'kindCode' => ZYICEnums::$coverageCode[$coverage->coverageCode],
                'amount' => $coverage->amount,
                'itemKind_Flag5' => '0',
            ];
            //车损险
            if (in_array($coverage->coverageCode, ['C02001', 'C12001'])) {
                $one['amount'] = $this->visitor->vehicleVisitor->negotiatedValue ?: $this->visitor->vehicleVisitor->actualValue;
            }
            //乘客险主险
            if (in_array($coverage->coverageCode, ['C05001', 'C15001'])) {
                $one['quantity'] = strval($this->visitor->getVehicleVisitor()->vehicleSeat - 1);
                $one['unitAmount'] = $coverage->unitAmount;
            }
            //乘客险附加险
            if (in_array($coverage->coverageCode, ['C05002', 'C05003', 'C15002', 'C15003'])) {
                $one['quantity'] = strval($this->visitor->getVehicleVisitor()->vehicleSeat - 1);
                $one['unitAmount'] = $coverage->amount;
                $one['amount'] = (string)floatval($one['quantity'] * $coverage->amount);
            }
            //修理期间天数
            if (in_array($coverage->coverageCode, ['C02003', 'C12003'])) {
                $one['quantity'] = intval($coverage->quantity);
                $one['unitAmount'] = $coverage->unitAmount;
            }
            //发动机进水损坏除外特约
            if (in_array($coverage->coverageCode, ['C02005', 'C12005'])) {
                $one['zoneCode'] = '0';
            }
            //绝对免赔率
            if (in_array($coverage->coverageCode, ['C02006', 'C03005', 'C04004', 'C05004', 'C12006', 'C13005', 'C14004', 'C15004'])) {
                $one['deductibleRate'] = $coverage->deductionRate;
            }
            //特约
            if (in_array($coverage->coverageCode, ['C08001', 'C08002', 'C08003', 'C08004', 'C18001', 'C18002', 'C18003', 'C18004'])) {
                $one['quantity'] = $coverage->serviceTimes;
            }
            //精神伤害抚慰金
            if (in_array($coverage->coverageCode, ['C03003', 'C04002', 'C05002', 'C13003', 'C14002', 'C15002'])) {
//                $one['unitAmount'] = $coverage->amount;
            }
            if ($coverage->coverageCode == 'C16001') {
                //附加电网保额
                $one['amount'] = $this->visitor->vehicleVisitor->negotiatedValue ?: $this->visitor->getVehicleVisitor()->actualValue;
            }
            //司机险
            if (in_array($coverage->coverageCode, ['C04001', 'C04002', 'C04003', 'C14001', 'C14002', 'C14003'])) {
                $one['quantity'] = 1;
                $one['unitAmount'] = $coverage->unitAmount ?: $coverage->amount;
            }

            //共享保额
            if (in_array($coverage->coverageCode, ['C03004', 'C04003', 'C05003', 'C13004', 'C14003', 'C15003'])) {
                $one['typeFlag'] = (int)$coverage->isShare;
                $this->shareAmountCheck($coverage->coverageCode, $coverage->unitAmount ?: $coverage->amount, $coverage->isShare);
            }

            $no += 1;

            $list[] = $one;
        }

        return $list;
    }

    /**
     * 新增设备险
     * @return array
     */
    private function getDeviceList(): array
    {
        $deviceList = [];
        if (!$this->visitor->getDeviceList()) {
            return $deviceList;
        }

        /*** @var PremiumDeviceVisitor $device */
        foreach ($this->visitor->getDeviceList() as $k => $device) {
            $deviceList[] = [
                'serialNo' => $k + 1,
                'deviceName' => $device->deviceName,
                'purchasePrice' => $device->purchasePrice,
                'buyDate' => $device->buyDate,
                'quantity' => $device->quantity,
                'actualValue' => $device->actualValue,
                'riskCode' => 'DEB',
                'itemNo' => $k + 1,
                'proposalNo' => $this->visitor->getExtInfoVisitor()->argc['proposalNoCI'] ?? '',
                'currency' => 'CNY',
            ];
        }

        return $deviceList;
    }

    /**
     * 通过身份证获取性别
     * @param $idCard
     * @return string
     * @throws Exception
     */
    private function getGenderByIDCard($idCard): string
    {
        if (strlen($idCard) != 18) {
            throw new Exception("身份证位数不合法");
        }
        $gender = intval(substr($idCard, 16, 1)) % 2;
        return $gender ? '1' : '2';
    }

    /**
     * 保外就医共享保额判定
     * @param $coverageCode
     * @param $amount
     * @param $isShare
     * @return void
     * @throws Exception
     */
    private function shareAmountCheck($coverageCode, $amount, $isShare)
    {
        if (!$isShare) {
            if ($amount > 100000) {
                if (!$amount % 100000) {
                    throw new Exception(IDockEnums::$coverageCode[$coverageCode] . '-请保证投保金额为10万元的整数倍');
                }
            } else {
                if (!in_array($amount, [5000, 10000, 20000, 50000, 100000, 150000, 200000, 300000, 500000, 1000000, 1500000, 2000000, 3000000, 4000000, 5000000])) {
                    throw new Exception('非共享' . IDockEnums::$coverageCode[$coverageCode] . '-请保证投保金额在' . '5000,10000，20000，50000，100000，150000，200000，300000，500000，1000000，1500000，2000000，3000000，4000000，5000000内');
                }
            }
        } else {
            //保外就医三者
            if ($coverageCode == 'C03004' or $coverageCode == 'C13004') {
                if ($amount > 1000000) {
                    if (!$amount % 1000000) {
                        throw new Exception(IDockEnums::$coverageCode[$coverageCode] . '-请保证投保金额为100万元的整数倍');
                    }
                } else {
                    if (!in_array($amount, [100000, 150000, 200000, 300000, 500000, 1000000, 1500000, 2000000, 3000000, 4000000, 5000000, 6000000, 8000000, 10000000])) {
                        throw new Exception('共享' . IDockEnums::$coverageCode[$coverageCode] . '-请保证投保金额在' . '100000，150000，200000，300000，500000，1000000，1500000，2000000，3000000，4000000，5000000，6000000，8000000，10000000内');
                    }
                }
            } else {
                if ($amount > 100000) {
                    if (!$amount % 100000) {
                        throw new Exception(IDockEnums::$coverageCode[$coverageCode] . '-请保证投保金额为10万元的整数倍');
                    }
                } else {
                    if (!in_array($amount, [10000, 20000, 30000, 40000, 50000, 100000, 150000, 200000, 300000, 500000, 1000000])) {
                        throw new Exception('共享' . IDockEnums::$coverageCode[$coverageCode] . '-请保证投保金额在' . '10000，20000，30000，40000，50000，100000，150000，200000，300000，500000，1000000内');
                    }
                }
            }
        }
    }
}
